<template>
  <el-drawer title="溯源" v-model="show" size="80%" @open="handleOpen" class="el-drawer--full">
    <div v-if="loading" class="loading">
      <!-- <app-loader /> -->
      <el-icon class="is-loading"><Loading /></el-icon>
      溯源中
    </div>

    <div class="main">
      <div class="container" ref="containerRef"></div>
      <div class="content" v-show="!loading">
        <div class="title">溯源分析</div>
        <div class="md">
          <app-markdown :content="traceData?.analysis" :typing="{ setp: 20, interval: 2 }" />
        </div>
      </div>
    </div>

    <TraceNodeDetail v-model="detail.show" :data="detail.data" />
  </el-drawer>
</template>

<script setup>
import { Graph, NodeEvent } from '@antv/g6'
// import traceData from '../trace.json'

import TraceNode from './TraceNode.vue'
import TraceNodeDetail from './TraceNodeDetail.vue'

const emits = defineEmits(['update:modelValue'])
const props = defineProps({
  modelValue: { type: Boolean, default: false },
  data: Object,
  loading: { type: Boolean, default: false },
})

const traceData = computed(() => {
  return props.data || {}
})

const detail = reactive({
  show: false,
  data: null,
})

const show = computed({
  get: () => props.modelValue,
  set: val => emits('update:modelValue', val),
})

watch(
  () => props.data,
  val => {
    if (val && show.value) initGraph()
  },
)

const containerRef = ref(null)
let graph

async function initGraph() {
  if (graph) graph.destroy()

  const res = traceData.value

  const nodes = []
  const edges = []

  for (const key in res.topology.topologyid) {
    const item = res.topology.topologyid[key]
    const node = {
      id: key,
      style: {
        // labelText: item.comm,
      },
    }

    // if (item.trace) {
    //   node.style.fill = '#EF4444'
    //   node.style.stroke = 'red'
    // }

    const dom = document.createDocumentFragment()
    const vm = createApp(TraceNode, {
      data: item,
      pid: key,
    }).mount(dom)

    node.type = 'html'
    node.style.size = [180, 50]

    // if (item.exe != '') {
    //   node.style.size = [180, 80]
    // }

    node.style.innerHTML = vm.$el

    nodes.push(node)
  }

  res.topology.related.forEach((item, index) => {
    edges.push({
      id: `edge-${index}`,
      // type: 'cubic-vertical',

      source: item.start.toString(),
      target: item.end.toString(),

      style: {
        stroke: '#3056E3',
        endArrow: true,

        // label: true,
        // labelText: services[item.secureType],
        // labelOffsetY: 15,
      },
    })
  })

  graph = new Graph({
    container: containerRef.value,
    width: containerRef.value.scrollWidth,
    height: containerRef.value.scrollHeight,
    // autoFit: 'view',
    // autoFit: 'view',
    autoFit: 'center',
    zoomRange: [0.1, 2],
    data: {
      nodes,
      edges,
    },

    node: {
      style: {
        // labelText: d => d.id,
        // labelPlacement: 'right',
        // labelBackground: true,
        // ports: [{ placement: 'right' }, { placement: 'left' }],
      },
      // animation: {
      //   enter: false,
      // },
    },
    edge: {
      type: 'cubic-horizontal',
    },
    layout: {
      // type: 'dagre',
      // rankdir: 'LR',
      // getWidth: () => 500, // 增加宽度
      // getHeight: () => 200, // 增加高度
      // getHGap: () => 400, // 增加水平间距
      // getVGap: () => 60, // 增加垂直间距

      type: 'antv-dagre',
      rankdir: 'LR',
      nodesep: 25, // 节点间距
      nodeSize: 100,
      ranksep: 100, // 线长度
    },
    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
  })

  graph.on(NodeEvent.CLICK, ev => {
    const { target } = ev

    detail.show = true
    detail.data = res.topology.topologyid[target.id]

    console.log('target', target)
  })

  graph.render()
}

const handleOpen = () => {
  // initGraph()
  if (graph) {
    graph.destroy()
    graph = null
  }
}

function isLeafNode(d) {
  return !d.children || d.children.length === 0
}
</script>

<style lang="scss" scoped>
.main {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.container {
  height: 60vh;
}

.content {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

.title {
  font-size: 16px;
  margin-bottom: 12px;
  font-weight: bold;
}

.md {
  flex: 1;
  overflow: auto;
}

.loading {
  display: flex;
  align-items: center;
  color: #999;
}
</style>
